# -*- coding: iso-8859-1 -*-

solution_file = (ARGV[0] or "solution.rb")
puts "Using solution file #{solution_file}"

load "TeXCheck.rb"
load "TeXGenerator.rb"
load solution_file

srand

# new function
def single_file
  begin
    TeXCheck::Checker::SINGLE_FILE
  rescue
    false
  end
end


def test(size = 50, seed = nil)
  result = Hash.new
  result['status'] = true
  result['ok'] = []
  result['nok'] = []

  srand( result['seed'] = seed || rand(9999999999) )

  # Create generator
  generator = TeXGenerator::Generator.new
  # Fill with random stuff
  generator.add_random(size)

  # Get reader & error list
  reader, generated_errors = generator.build(if single_file then 0 else rand(10) + 2 end)    # changed
  result['files'] = reader.to_s
  result['generated errors'] = generated_errors

  # Load document using TeXFile
  tex = TeXCheck::TeXFile.load( reader, "main.tex" )

# Removed next line (it made the first test quite useless)
#  result['Read using TeXFile.load'] = generated_lines = tex.lines

  result['Read using TeXFile.load'] = tex.lines  # added
  generated_lines = generator.lines              # added
  result['generated lines'] = generated_lines    # added


  # Check read lines one by one
  tex.lines.each_with_index do |line, idx|
    if line.contents != generated_lines[idx].contents then
      result['error line index'] = idx
      result['error expected line'] = generated_lines[idx].contents
      result['error read line'] = line
      result['error'] = "Failed read"
      result['status'] = false

      result['nok'] += [ "reading" ]

      return result
    end
  end

  # Reading has succeeded
  result['ok'] += [ "reading" ]


  # Create checker
  checker = TeXCheck::Checker.new
  # Get a list of errors
  found_errors = checker.check(tex).sort

  # Check the errors by type
  # This line looks for all classes ending in Error
  TeXCheck.constants.select { |c| c.to_s =~ /.Error$/ }.each do |errconstant|
    # errconstant is the name of an Error subclass

    # Get the class with name <errconstant>
    errclass = TeXCheck.const_get(errconstant)
    # Get the generated errors by type
    gerrs = generated_errors.select { |err| err.class == errclass }
    # Get the found errors by type
    ferrs = found_errors.select { |err| err.class == errclass }

    result["expected #{errclass.name}"] = gerrs.length
    result["found #{errclass.name}"] = ferrs.length

    # We expect both lists to be of equal length
    if ferrs.length != gerrs.length
      result['status'] = false
      result['nok'] += [ errclass.name ]
    else
      # Both lists have same length
      # Now check that their contents are the same
      not_caught = gerrs.remove(ferrs)
      invented = ferrs.remove(gerrs)

      if not_caught.empty? && invented.empty? then
        result['ok'] += [ errclass.name ]
      else
        result['status'] = false
        result['uncaught #{errclass.name}'] = not_caught
        result['invented #{errclass.name}'] = invented
        result['nok'] += [ errclass.name ]
      end
    end
  end

  result
end




$failure = Hash.new("false")
$total_score = 0

10.times do
  result = test(50)

  unless result['status']
    result.to_a.each do |k, v|
      puts k
      puts v
      puts "---"
    end

    result['nok'].each { |x| $failure[x] = true }
  end

  $total_score += result['ok'].length
  puts "Score: #{result['ok'].length}"
end


puts "Failures detected: #{$failure.keys.join(', ')}"
puts "Total score: #{$total_score}"
puts "Flawless #{if single_file then '(single file)' else '(multiple files)' end}" if $failure.size == 0

if single_file then
  puts "Warning: single file yields a lower grade"
end
